#include "UtilidadesConstantes.h"
#include "Escenario.h"
#include "Cerdito.h"

using namespace std;
using namespace TP::Juego::Arena;

Escenario::Escenario() {
	this->_perimetro = NULL;
}

Escenario::Escenario(unsigned pAlto, unsigned pAncho,
		const string &rutaImagenFondo) {
	this->_perimetro = new Perimetro(pAlto, pAncho);
	_ruta_imagen_fondo = rutaImagenFondo;
}

Escenario::~Escenario() {
	for (unsigned int i = 0; i < _actores.size(); ++i) {
		delete _actores[i];
	}
	for (unsigned int i = 0; i < _utilidades.size(); ++i) {
		delete _utilidades[i];
	}
	for (unsigned int i = 0; i < _semillasGeneradorPajaritos.size(); ++i) {
		delete _semillasGeneradorPajaritos[i];
	}
	if (_perimetro != NULL) {
		delete this->_perimetro;
	}
}

// Recibe punteros creados con new */

Actor* Escenario::addActor(Actor* pActor, Posicion* pPosicion,
		Vector2D* pVelocidad, Vector2D* pAceleracion) {

	if (pActor && pPosicion && pVelocidad) {
		/* Construyo la trayectoria que debe tener el actor dentro de la arena
		 * de juego */
		Trayectoria* trayectoria = new Trayectoria(pPosicion, pVelocidad,
				pAceleracion);

		if (trayectoria) {
			// Le asigno la trayectoria al actor.
			pActor->setTrayectoria(trayectoria);
			// Agrego al actor a la arena de juego.
			this->_actores.push_back(pActor);
		}
	}
	return pActor;
}

Actor* Escenario::getActorPorNombre(const string& pNombreActor) {
	Actor* actorReturn = NULL;
	for (int cur = 0; cur < this->_actores.size(); cur++) {
		if (pNombreActor == this->_actores[cur]->Nombre()) {
			actorReturn = this->_actores[cur];
			break;
		}
	}
	return actorReturn;
}

vector<Actor*>& Escenario::getActores() {
	return this->_actores;
}

Utilidad* Escenario::addUtilidad(Utilidad* pUtilidad, Posicion* pPosicion) {
	if (pUtilidad && pPosicion) {
		pUtilidad->setPosicion(pPosicion);
		this->_utilidades.push_back(pUtilidad);
	}
	return pUtilidad;
}

vector<Utilidad*>& Escenario::getUtilidades() {
	return this->_utilidades;
}

Perimetro* Escenario::getPerimetro() {
	return this->_perimetro;
}

void Escenario::getVectorPisos(vector<Piso*> &aEscribir) {
	aEscribir.clear();
	unsigned cur = 0;
	while (cur < _utilidades.size()) {
		if (_utilidades[cur]->getRol()->Nombre() == ROL_PISO) {
			aEscribir.push_back(dynamic_cast<Piso*>(_utilidades[cur]->clonar()));
		}
		++cur;
	}
}

vector<struct InfoMov*>& Escenario::getSemillasGeneradorPajaritos() {
	return this->_semillasGeneradorPajaritos;
}

struct InfoMov* Escenario::setSemillaGeneradorPajaritos(
		struct InfoMov* pSemilla) {
	this->_semillasGeneradorPajaritos.push_back(pSemilla);
}

Escenario* Escenario::clonar() {
	Escenario *escenario = new Escenario(_perimetro->getAlto(),
			_perimetro->getAncho(), _ruta_imagen_fondo);

	// No se necesita clonar Actores, si se necesitase, agregarlo
	for (unsigned i = 0; i < _utilidades.size(); ++i) {
		escenario->_utilidades.push_back(_utilidades[i]->clonar());
	}
	for (unsigned i = 0; i < _semillasGeneradorPajaritos.size(); ++i) {
		escenario->_semillasGeneradorPajaritos.push_back(_semillasGeneradorPajaritos[i]->clonar());
	}
	return escenario;
}

const string& Escenario::getRutaImagenFondo() const {
	return _ruta_imagen_fondo;
}

void Escenario::liberar() {
	if (_perimetro != NULL) {
		delete this->_perimetro;
		this->_perimetro = NULL;
	}
	// Elimino los actores del escenario liberando los recursos.
	for (int cur = 0; cur < this->_actores.size(); cur++)
		delete this->_actores[cur];
	this->_actores.clear();
	// Elimino las utilidades del Escenario liberando los recursos.
	for (int cur = 0; cur < this->_utilidades.size(); cur++)
		delete this->_utilidades[cur];
	this->_utilidades.clear();
	// Elimino los semilleros del Escenario liberando los recursos.
	for (int cur = 0; cur < this->_semillasGeneradorPajaritos.size(); cur++)
		delete this->_semillasGeneradorPajaritos[cur];
	this->_semillasGeneradorPajaritos.clear();
}

string Escenario::aXML() {
	TiXmlDocument* doc = new TiXmlDocument();
	TiXmlDeclaration * decl = new TiXmlDeclaration("1.0", "", "");
	doc->LinkEndChild(decl);

	doc->LinkEndChild(this->aElementoXML());

	TiXmlPrinter printer;
	doc->Accept(&printer);
	return printer.CStr();
}

string Escenario::aXML(const string& pPath) {
	TiXmlDocument* doc = new TiXmlDocument(pPath.c_str());
	TiXmlDeclaration * decl = new TiXmlDeclaration("1.0", "", "");
	doc->LinkEndChild(decl);

	doc->LinkEndChild(this->aElementoXML());

	TiXmlPrinter printer;
	doc->Accept(&printer);
	return printer.CStr();
}

void Escenario::parseXML(const string& pDescriptor) {
	TiXmlDocument doc;
	doc.Parse(pDescriptor.c_str(), 0, TIXML_ENCODING_UTF8);
	this->deElementoXML(doc.FirstChildElement());
}

TiXmlElement* Escenario::aElementoXML() {
	TiXmlElement * escenarioXML = new TiXmlElement("Escenario");

	// Serializo el path a la imagen de fondo.
	escenarioXML->SetAttribute("ruta_imagen_fondo", this->_ruta_imagen_fondo.c_str());

	// Serializo la lista de actores.
	TiXmlElement * elemento = new TiXmlElement("Actores");

	for (size_t cur = 0; cur < _actores.size(); cur++) {
		// DEBUG.
		Actor* actor = _actores[cur];
		if (actor)
			elemento->LinkEndChild(actor->aElementoXML());
	}

	escenarioXML->LinkEndChild(elemento);

	// Serializo las utilidades.
	elemento = new TiXmlElement("Utilidades");

	for (int cur = 0; cur < _utilidades.size(); cur++)
		elemento->LinkEndChild(_utilidades[cur]->aElementoXML());

	escenarioXML->LinkEndChild(elemento);

	// Serializo las semillas
	elemento = new TiXmlElement("Semillero");

	for (int cur = 0; cur < _semillasGeneradorPajaritos.size(); cur++) {
		elemento->LinkEndChild(_semillasGeneradorPajaritos[cur]->aElementoXML());
	}

	escenarioXML->LinkEndChild(elemento);

	// Serializo el perimetro.
	if (NULL != this->_perimetro)
		escenarioXML->LinkEndChild(this->_perimetro->aElementoXML());
	else
		escenarioXML->LinkEndChild(new TiXmlElement("NULL"));

	return escenarioXML;
}

void Escenario::deElementoXML(TiXmlElement* pElemento) {
	if (pElemento->ValueTStr() == "Escenario") {
		// Hidrato el path de la imagend e fondo.
		this->_ruta_imagen_fondo = pElemento->Attribute("ruta_imagen_fondo");

		// Hidrato los actores.
		TiXmlElement* actores = pElemento->FirstChildElement();
		TiXmlElement* cursor = actores->FirstChildElement();
		while (NULL != cursor) {
			Actor* actor = Actor::deElementoXMLGenerico(cursor);
			if (NULL != actor)
				this->_actores.push_back(actor);
			cursor = cursor->NextSiblingElement();
		}

		// Hidrato la lista de utilidades.
		TiXmlElement* utilidades = actores->NextSiblingElement();
		cursor = utilidades->FirstChildElement();
		while (cursor != NULL) {
			Utilidad* utilidad = Utilidad::deElementoXMLGenerico(cursor);
			if (utilidad)
				this->_utilidades.push_back(utilidad);
			cursor = cursor->NextSiblingElement();
		}

		// Hidrato la lista de semillas.
		TiXmlElement* semillas = utilidades->NextSiblingElement();
		cursor = semillas->FirstChildElement();
		while (cursor != NULL) {
			struct InfoMov *info = new struct InfoMov;
			info->deElementoXML(cursor);
			if (info)
				this->_semillasGeneradorPajaritos.push_back(info);
			cursor = cursor->NextSiblingElement();
		}

		TiXmlPrinter printer;
		pElemento->Accept(&printer);
		//	cout << endl <<  printer.CStr() << endl;

		// Hidrato el perimetro
		TiXmlElement* perimetro = semillas->NextSiblingElement();
		if ("NULL" != perimetro->ValueTStr()) {
			this->_perimetro = new Perimetro();
			this->_perimetro->deElementoXML(perimetro);
		}
	}
}

Utilidad* Escenario::getCerditoAvatar() {
	Utilidad* avatar = NULL;
	for (vector<Utilidad*>::iterator it = _utilidades.begin();
			it != _utilidades.end() && NULL == avatar; ++it) {

		if ((*it)->getRol()->Nombre() == ROL_CERDITO) {
			if (((Cerdito*)(*it))->getPropietario() == NULL)
				avatar = (Utilidad*)(*it);
		}
	}
	return avatar;
}

Utilidad* Escenario::getCerditoAvatarPorJugador(Jugador* pJugador) {
	Utilidad* avatar = NULL;
	for (vector<Utilidad*>::iterator it = _utilidades.begin(); 
			it != _utilidades.end() && NULL == avatar; ++it) {
		if (ROL_CERDITO == (*it)->getRol()->Nombre()) {
			if (((Cerdito*)(*it))->getPropietario() != NULL) {
				if (*(((Cerdito*)(*it))->getPropietario()) == *pJugador)
					avatar = (Utilidad*)(*it);
			}
		}
	}
	return avatar;
}